// 按需修改
import {modal, toPath} from "../commonUtils";

const TIME_OUT = 8000
import {apiPath, baseUrl, tenantId} from '@/utils/config';
import {
    clearStorage,
    getRefreshToken,
    getToken,
    postRefreshToken,
    REFRESH_TOKEN_KEY,
    TOKEN_KEY
} from './auth' // 假设你有身份验证工具函数

// 请求配置
interface HttpOption extends Partial<UniApp.RequestOptions> {
    // 是否自动显示 toast
    showToast?: boolean
}

// 响应格式（可和你们的后端约定）
interface HttpResponse<T = any> {
    code: number
    msg: string
    data: T
}

class Http {
    // 请求拦截器队列
    private reqInterceptors: Array<(options: HttpOption) => HttpOption | Promise<HttpOption>> = []
    // 响应拦截器队列
    private resInterceptors: Array<(res: any) => any | Promise<any>> = []

    // 添加请求拦截器
    useReq(fn: (options: HttpOption) => HttpOption | Promise<HttpOption>) {
        this.reqInterceptors.push(fn)
        return this
    }

    // 添加响应拦截器
    useRes(fn: (res: any) => any | Promise<any>) {
        this.resInterceptors.push(fn)
        return this
    }

    // 核心请求
    async request<T = any>(options: HttpOption): Promise<T> {
        const token = await getToken()
        // 1. 合并默认配置
        let opts: HttpOption = {
            url: '',
            method: 'GET',
            timeout: TIME_OUT,
            header: {
                'Content-Type': 'application/json',
                // 可统一加 token
                'Authorization': token,
                'tenant-id': tenantId
            },
            showToast: true,
            ...options,
        }
        // 补全 baseURL
        if (!opts.url.startsWith('http')) {
            opts.url = baseUrl + apiPath + opts.url
        }

        // 2. 执行请求拦截器链
        for (const fn of this.reqInterceptors) {
            opts = await fn(opts)
        }

        // 3. 真正发请求
        return new Promise((resolve, reject) => {
            uni.request({
                ...opts,
                success: async (result) => {
                    const {data, statusCode} = result as any
                    // 4. 先跑响应拦截器
                    let res = data
                    for (const fn of this.resInterceptors) {
                        res = await fn(res)
                    }
                    // 5. 约定 code === 200 表示业务成功
                    if (res?.code === 0) {
                        resolve(res)
                    } else {
                        if (opts.showToast) {
                            uni.showToast({title: res?.msg || '请求失败', icon: 'none'})
                        }
                        reject(res)
                    }
                },
                fail: (err) => {
                    if (opts.showToast) {
                        uni.showToast({title: err.errMsg || '网络错误', icon: 'none'})
                    }
                    reject(err)
                },
            })
        })
    }

    // 快捷方法
    get<T>(url: string, params?: any, options?: HttpOption) {
        return this.request<T>({
            url,
            method: 'GET',
            data: params,
            ...options,
        })
    }

    post<T>(url: string, data?: any, options?: HttpOption) {
        return this.request<T>({
            url,
            method: 'POST',
            data,
            ...options,
        })
    }

    put<T>(url: string, data?: any, options?: HttpOption) {
        return this.request<T>({
            url,
            method: 'PUT',
            data,
            ...options,
        })
    }

    delete<T>(url: string, data?: any, options?: HttpOption) {
        return this.request<T>({
            url,
            method: 'DELETE',
            data,
            ...options,
        })
    }
}

// 单例导出
const http = new Http()


// 全局请求拦截器示例：自动带 token
http.useReq((opts) => {
    const token = uni.getStorageSync('TOKEN')
    if (token) {
        opts.header = {
            ...opts.header,
            Authorization: `Bearer ${token}`,
        }
    }
    return opts
})


// 1. 新增三个变量
let isRefreshing = false               // 是否正在刷新中
let waitList: Array<() => void> = []   // 等待队列

// 2. 把原来的 useRes 拦截器整块替换
http.useRes(async (res, config?: HttpOption & { _retry?: boolean }) => {
    if (res?.code !== 401) return res
    if (config?._retry) return Promise.reject(res)

    if (!isRefreshing) {
        isRefreshing = true
        try {
            const rfToken = getRefreshToken()
            if (!rfToken) {
                const data = await modal('提示', '未登录', '去登录')
                if (data) {
                    toPath('/pages/login/login')
                    clearStorage()
                }
            }

            const {code, data} = await postRefreshToken(rfToken) // 换token
            if (code !== 0 || !data?.accessToken) {
                const data = await modal('提示', '登录凭证刷新错误', '去登录')
                if (data) {
                    toPath('/pages/login/login')
                    clearStorage()
                }
            }

            uni.setStorageSync(TOKEN_KEY, data.accessToken)   // 存新token
            if (data.refreshToken) uni.setStorageSync(REFRESH_TOKEN_KEY, data.refreshToken)

            // 重放队列
            waitList.forEach(fn => fn())
            waitList = []

            // 重试当前请求（带上新token）
            return http.request({...config, _retry: true} as HttpOption)
        } catch (e) {
            waitList = []          // 清空队列
            const data = await modal('提示', '未登录', '去登录')
            if (data) {
                toPath('/pages/login/login')
                clearStorage()
            }
            return Promise.reject(res)
        } finally {
            isRefreshing = false
        }
    } else {
        // 其它请求排队
        return new Promise((resolve, reject) => {
            waitList.push(() => {
                http.request({...config, _retry: true} as HttpOption)
                    .then(resolve)
                    .catch(reject)
            })
        })
    }
})

// 全局响应拦截器示例：401 自动跳转登录
// http.useRes(async (res, config?: HttpOption & { _skipAuth?: boolean }) => {
//     if (res?.code === 401 && !config?._skipAuth) {
//         // 普通业务 401，才弹登录
//         const data = await modal('提示', '未登录', '去登录')
//         if (data) {
//             toPath('/pages/login/login')
//             removeToken()
//         }
//     }
//     return res
// })

export default http